package com.exchange.controller.app.user;

import com.aliyun.oss.OSSClient;
import com.exchange.common.model.CoinConfig;
import com.exchange.common.model.User;
import com.exchange.common.model.UserWallet;
import com.exchange.constant.AppConst;
import com.exchange.constant.BizConst;
import com.exchange.constant.EhcacheConstant;
import com.exchange.constant.EmailConst;
import com.exchange.interceptor.EnumError;
import com.exchange.util.BizUtils;
import com.exchange.util.EmailUtils;
import com.exchange.util.SMSUtils;
import com.exchange.util.aliOSSFileUtil;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.ehcache.CacheKit;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.jfinal.upload.UploadFile;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class UserService {
	
	private Cache rides = Redis.use(PropKit.get("redisName"));

	public Ret sendRegisterMessage(int type, String to) {

		String oldcode = CacheKit.get(EhcacheConstant.RegisterCode, to);
		if (StrUtil.isNotBlank(oldcode)) {// 存在验证码
			return Ret.fail("msg", EnumError.SMS_VCode_Sent.getCode());
		}
		String sql;
		if (type == BizConst.MOBILE) {// 手机
			sql = "SELECT COUNT(id) FROM t_user WHERE phone = ? AND state = 1 ";
		} else {// 邮箱
			sql = "SELECT COUNT(id) FROM t_user WHERE email = ? AND state = 1 ";
		}
		// 判断是否存在
		int nu = Db.queryInt(sql, to);
		if (nu > 0) {
			return Ret.fail("msg", EnumError.ACCOUNT_NUM_MAX.getCode());
		}
		// 发送验证码
		String code = RandomUtil.randomNumbers(AppConst.DEFAULT_CODE_LENGTH);
		// 保存缓存
		CacheKit.put(EhcacheConstant.RegisterCode, to, code);
		// 发送验证码
		if (type == BizConst.MOBILE) {
			// 发送短信验证码
			SMSUtils.sendMessage(BizConst.SMS_TYPE_REGISTER, to, code);
		} else {
			// 发送邮箱验证码
			EmailUtils.sendMessage(BizConst.SMS_TYPE_REGISTER, to, EmailConst.EMAIL_CAPTCHA_REGISTER, code);
		}
		return Ret.ok();
		
	}

	public Ret register(String account, String password, String to, String vcode, int type, String invitationCode) {
		// 获取缓存数据[注册验证类]
		String captcha = CacheKit.get(EhcacheConstant.RegisterCode, to);
		// 判断验证码
		if (StrUtil.isEmpty(captcha) || !StrUtil.equals(captcha, vcode)) {
			return Ret.fail("msg", EnumError.SMS_VCode_INVALID.getCode());
		}
		// 账号是否已经占用
		int nu = Db.queryInt("SELECT COUNT(id) FROM t_user WHERE account = ?", account);
		if (nu > 0) {
			return Ret.fail("msg", EnumError.REGISTERED.getCode());
		}
		// 注册用户信息
		String md5word = SecureUtil.md5(StrUtil.addSuffixIfNot(password, BizConst.BIZ_SECRET_CODE));
		User parent = null;
		if(StrUtil.isNotBlank(invitationCode)) {
			parent = User.dao.findFirst("SELECT id,authority FROM t_user WHERE invitationCode = ? AND state = 1 ", invitationCode);
		}
		User user = new User().setAccount(account).setPassword(md5word).setCipher(md5word).setCreateTime(new Date()).setNickName(account);
		if (type == BizConst.MOBILE) {
			user.setPhone(to);
		} else {
			user.setEmail(to);
		}
		boolean b = user.save();
		//只有有上级的才会生成自己的邀请码
		if (b && BeanUtil.isNotEmpty(parent)) {
			String myInvitationCode = RandomUtil.randomString(AppConst.DEFAULT_INVITATION_CODE_SIZE);
			user.setInvitationCode(myInvitationCode);
			user.setParentId(parent.getId());
			StringBuffer authority = new StringBuffer(parent.getAuthority());
			user.setAuthority(authority.append(user.getId()).append('_').toString());
			boolean b2 = user.update();
			if (!b2) {
				return Ret.fail("msg", EnumError.invitation_fail.getCode());
			}
		}
		if (!b) {
			return Ret.fail("msg", EnumError.register_fail.getCode());
		}
		// 创建钱包
		// TODO 绑定用户和钱包地址(String userAccount, String sonServerName)http传入钱包服务
		Map<String, Object> paramMap = MapUtil.newHashMap();
		paramMap.put("userAccount", account);
		paramMap.put("sonServerName", "sonServerName");
		String re = HttpUtil.post("钱包服务地址bindingAddress", paramMap);
		JSONObject jsonObject = JSONUtil.parseObj(re);
		boolean state = jsonObject.getBool("Success");

		// TODO 这里先改成不保存钱包地址
		Date date = new Date();
		List<CoinConfig> list = CoinConfig.dao.findAll();// 获取钱包种类
		for (CoinConfig coinConfig : list) {
			new UserWallet().setUserId(user.getId()).setCoin(coinConfig.getCoin()).setUpdateTime(date)
					.setCreateTime(date).save();
		}

		return Ret.ok();

	}

	public Ret login(String account, String password) {
		
		String Pwd = SecureUtil.md5(StrUtil.addSuffixIfNot(password, BizConst.BIZ_SECRET_CODE));
		User user = User.dao.findFirst("SELECT * FROM t_user WHERE account = ? AND password = ? AND state = 1 ", account, Pwd);
		if(BeanUtil.isEmpty(user)) {
			return Ret.fail("msg", EnumError.ACCOUNT_OR_PASSWORD_ERROR.getCode());
		}
        // 设置token
		String token = IdUtil.simpleUUID();
		rides.setex(token, AppConst.USER_LOGIN_TIME, account);
		rides.setex(account, AppConst.USER_TIME, user);
		//设置返回的用户数据
		user.set("token", token);
		user.set("expires", AppConst.USER_UNAUTHORIZED);// 资金密码授权情况
		user.setRank(user.getRank() > user.getAdminRank() ? user.getRank() : user.getAdminRank());//账户的最终等级
		user.remove("adminRank","password","cipher","authority");
       
        return Ret.ok("user", user);
    }

	public Ret fCaptcha(int type, String account) {
        
		User user = User.dao.findFirst("SELECT * FROM t_user WHERE account = ? AND state = 1 ", account);
		if(BeanUtil.isEmpty(user)) {
			return Ret.fail("msg", EnumError.ACCOUNT_NO.getCode());
		}
		String oldcode = CacheKit.get(EhcacheConstant.undateCode, account);
		if (StrUtil.isNotBlank(oldcode)) {// 存在验证码
			return Ret.fail("msg", EnumError.SMS_VCode_Sent.getCode());
		} 
		String code = RandomUtil.randomNumbers(AppConst.DEFAULT_CODE_LENGTH);
		// 保存缓存
		CacheKit.put(EhcacheConstant.undateCode, account, code);	
		// 发送验证码
		if (type == BizConst.MOBILE) {
			// 发送短信验证码
			SMSUtils.sendMessage(BizConst.SMS_TYPE_CIPHER, user.getPhone(), code);
		} else {
			// 发送邮箱验证码
			EmailUtils.sendMessage(BizConst.SMS_TYPE_CIPHER, user.getEmail(), EmailConst.EMAIL_CAPTCHA_FORGET, code);
		}
		return Ret.ok();
		
    }
	
	public Ret forget(String account, String vcode, String newPassword) {
		
		String captcha = CacheKit.get(EhcacheConstant.undateCode, account);
		// 判断验证码
		if (StrUtil.isEmpty(captcha) || !StrUtil.equals(captcha, vcode)) {
			return Ret.fail("msg", EnumError.SMS_VCode_INVALID.getCode());
		}
		String password = SecureUtil.md5(StrUtil.addSuffixIfNot(newPassword, BizConst.BIZ_SECRET_CODE));
		// 修改密码 
        Db.update("UPDATE t_user SET password = ? WHERE account = ? AND state = 1", password, account);
		
        return Ret.ok();
    }
	
	public Ret mdfLoginPassword (User user, String token, String oldPassword, String newPassword) {
		
		String pwd = SecureUtil.md5(StrUtil.addSuffixIfNot(oldPassword, BizConst.BIZ_SECRET_CODE));
		if(StrUtil.equals(user.getPassword(), pwd)) {
			return Ret.fail("msg", EnumError.PASSWORD_ERROR.getCode());
		}
		// 新密码
        String nPwd = SecureUtil.md5(StrUtil.addSuffixIfNot(newPassword, BizConst.BIZ_SECRET_CODE));
		user.setPassword(nPwd).update();
		//修改密码后需要重新登陆
		rides.del(token,user.getAccount());
		
		return Ret.ok();
		
    }
	
	public Ret mdfTradePassword(User user, String token, String vcode, String newTradePassword) {
		// 获取缓存数据[注册验证类]
		String captcha = CacheKit.get(EhcacheConstant.undatePayCode, token);
		// 判断验证码
		if (StrUtil.isEmpty(captcha) || !StrUtil.equals(captcha, vcode)) {
			return Ret.fail("msg", EnumError.SMS_VCode_INVALID.getCode());
		}
		//更新数据库
		String pwd = SecureUtil.md5(StrUtil.addSuffixIfNot(newTradePassword, BizConst.BIZ_SECRET_CODE));
		user.setCipher(pwd).update();
		//更新内存
		user.set("expires", AppConst.USER_UNAUTHORIZED);// 资金密码授权情况
		rides.set(user.getAccount(), user);
		
		return Ret.ok();
		
    }
	
	public Ret captcha(User user, String token) {
		String code = RandomUtil.randomNumbers(AppConst.DEFAULT_CODE_LENGTH);
		if(!StrUtil.isEmpty(user.getPhone())) {
			SMSUtils.sendMessage(BizConst.SMS_TYPE_PAY_CIPHER, user.getPhone(), code);
		} else {
			EmailUtils.sendMessage(BizConst.SMS_TYPE_PAY_CIPHER, user.getEmail(), EmailConst.EMAIL_CAPTCHA_CIPTCHER, code);
		}
		// 保存缓存
		CacheKit.put(EhcacheConstant.undatePayCode, token, code);
		
		return Ret.ok();
    }
	
	public Ret authorization(User user, String token, String cipher) {

		String ins = SecureUtil.md5(StrUtil.addSuffixIfNot(token, BizConst.BIZ_SECRET_CODE));
		if (!StrUtil.equals(ins, user.getCipher())) {
			return Ret.fail("msg", EnumError.CIPHER_PASSWORD_ERROR.getCode());
        }
		// 设置 交易有效时长
		user.set("expires", BizUtils.getAuthExpires());// 资金密码授权情况
        rides.set(user.getAccount(), user);
        
        return Ret.ok();
	}
	
	public Ret logout(String token) {
		String account = rides.get(token);
		if(!StrUtil.isEmpty(account)) {
			rides.del(account);
		}
		rides.del(token);
		return Ret.ok();
	}
	
	public Ret bCaptcha(User user, int type, String to) {
		String oldcode = CacheKit.get(EhcacheConstant.bangdingCode, to);
		if (StrUtil.isNotBlank(oldcode)) {// 存在验证码
			return Ret.fail("msg", EnumError.SMS_VCode_Sent.getCode());
		}
		String code = RandomUtil.randomNumbers(AppConst.DEFAULT_CODE_LENGTH);
		if(type == BizConst.MOBILE && StrUtil.isEmpty(user.getPhone())) {
			SMSUtils.sendMessage(BizConst.SMS_TYPE_BINGDING, to, code);
		}else if(type == BizConst.EMAIL && StrUtil.isEmpty(user.getEmail())){
			EmailUtils.sendMessage(BizConst.SMS_TYPE_BINGDING, to, EmailConst.EMAIL_CAPTCHA_BIND, code);
		}
		CacheKit.put(EhcacheConstant.bangdingCode, to, code);
		
		return Ret.ok();
	}
	
	public Ret bind(User user, int type, String to, String vcode) {

		String captcha = CacheKit.get(EhcacheConstant.bangdingCode, to);
		//判断验证码
        if (StrUtil.isEmpty(captcha) || !StrUtil.equals(captcha, vcode)) {
        	return Ret.fail("msg", EnumError.SMS_VCode_INVALID.getCode());
        }
		if(type == BizConst.MOBILE && StrUtil.isEmpty(user.getPhone())) {
			user.setPhone(to).update();
			rides.set(user.getAccount(),user);
		}else if(type == BizConst.EMAIL && StrUtil.isEmpty(user.getEmail())){
			user.setEmail(to).update();
			rides.set(user.getAccount(),user);
		}else {
			return Ret.fail("msg", EnumError.already_binding.getCode());
		}
		
		return Ret.ok();
	}
	
	public Ret addInvitationCode(User user, String invitationCode) {
  		
   		//邀请码是否为空
		if(ObjectUtil.isNotNull(user.getParentId())) {
			return Ret.fail("msg", EnumError.No_need_add.getCode());
		}
		//邀请码是否存在
		User parent = User.dao.findFirst("SELECT id,authority FROM t_user WHERE invitationCode = ? AND state = 1 ");
   		if(BeanUtil.isEmpty(parent)) {
   			return Ret.fail("msg", EnumError.invitation_NULL.getCode());
   		}
        //添加父级id
        user.setParentId(parent.getId());
		StringBuffer authority = new StringBuffer(parent.getAuthority());
		user.setAuthority(authority.append(user.getId()).append('_').toString());
		boolean b2 = user.update();
		if (!b2) {
			return Ret.fail("msg", EnumError.invitation_fail.getCode());
		}
		rides.set(user.getAccount(),user);
   		
		return Ret.ok();
   		
   	}
	
	public Ret upload(User user, UploadFile header) {
		
		OSSClient ossClient = aliOSSFileUtil.getOSSClient();
//        File file = new File(header.getUploadPath() + "/" + header.getOriginalFileName());
        String picUrl = aliOSSFileUtil.uploadImg(ossClient, header.getFile(), PropKit.get("bucketApp"));
        
        user.setHeadImage(picUrl).update();
        rides.set(user.getAccount(),user);
        
        return Ret.ok("url",picUrl);
		
	}
	
	
	
	
	
	
	
	
}
